home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / QuickTime VR / MacOS / QuickDraw™ 3D 1.0.6F4 SDK / Samples / SampleCode / GeometryTest / GTSupport.c < prev    next >
Encoding:
Text File  |  1995-05-03  |  13.9 KB  |  512 lines  |  [TEXT/MPCC]

  1. // My3dSupport.c - QuickDraw 3d routines
  2. //
  3. // This file contains utility routines for QuickDraw 3d sample code.
  4. // Shows how to read a metafile and render it.
  5. //
  6. // Created 27th Dec 1994, Nick Thompson, DEVSUPPORT
  7.  
  8.  
  9. #include <Files.h>
  10. #include <QuickDraw.h>
  11. #include <QDOffScreen.h>
  12. #include <StandardFile.h>
  13.  
  14. #include "GTSupport.h"
  15.  
  16. #include "QD3D.h"
  17. #include "QD3DDrawContext.h"
  18. #include "QD3DRenderer.h"
  19. #include "QD3DShader.h"
  20. #include "QD3DCamera.h"
  21. #include "QD3DLight.h"
  22. #include "QD3DGeometry.h"
  23. #include "QD3DTransform.h"
  24. #include "QD3DGroup.h"
  25. #include "QD3DMath.h"
  26.  
  27. #include "QD3DStorage.h"
  28. #include "QD3DIO.h"
  29.  
  30.  
  31. //-----------------------------------------------------------------------------------------------
  32. // local utility functions
  33.  
  34. void GetGroupBBox(
  35.     DocumentHdl            theDocument,
  36.     TQ3BoundingBox         *viewBBox) ;
  37.                                                 
  38. static TQ3Status GetDocumentGroupBoundingBox( 
  39.     DocumentHdl theDocument , 
  40.     TQ3BoundingBox *viewBBox) ;
  41.  
  42. //-----------------------------------------------------------------------------------------------
  43. // Submit the scene for rendering/fileIO and picking
  44. TQ3Status SubmitScene( DocumentHdl theDocument ) 
  45. {        
  46.     TQ3Vector3D                globalScale;
  47.     TQ3Vector3D                globalTranslate;
  48.     
  49.     globalScale.x = globalScale.y = globalScale.z = (**theDocument).fGroupScale;
  50.     globalTranslate = *(TQ3Vector3D *)&(**theDocument).fGroupCenter;
  51.     Q3Vector3D_Scale(&globalTranslate, -1, &globalTranslate);
  52.     Q3Style_Submit((**theDocument).fInterpolation, (**theDocument).fView);
  53.     Q3Style_Submit((**theDocument).fBackFacing , (**theDocument).fView);
  54.     Q3Style_Submit((**theDocument).fFillStyle, (**theDocument).fView);
  55.         
  56.     Q3MatrixTransform_Submit( &(**theDocument).fRotation, (**theDocument).fView);
  57.         
  58.     Q3ScaleTransform_Submit(&globalScale, (**theDocument).fView);
  59.     Q3TranslateTransform_Submit(&globalTranslate, (**theDocument).fView);
  60.     
  61.     Q3Shader_Submit( (**theDocument).fShader, (**theDocument).fView ) ;
  62.     Q3DisplayGroup_Submit( (**theDocument).fModel, (**theDocument).fView);
  63.     
  64.     return kQ3Success ;
  65. }
  66.  
  67. //-----------------------------------------------------------------------------------------------
  68.  
  69. static TQ3Status GetDocumentGroupBoundingBox( 
  70.     DocumentHdl theDocument , 
  71.     TQ3BoundingBox *viewBBox)
  72. {
  73.     TQ3Status        status;
  74.     TQ3ViewStatus    viewStatus ;
  75.     
  76.     status = Q3View_StartBoundingBox( (**theDocument).fView, kQ3ComputeBoundsApproximate );
  77.     do {
  78.         status = SubmitScene( theDocument ) ;
  79.     } while((viewStatus = Q3View_EndBoundingBox( (**theDocument).fView, viewBBox )) == kQ3ViewStatusRetraverse );
  80.     return status ;
  81. }
  82.  
  83. //-----------------------------------------------------------------------------------------------
  84.  
  85. TQ3ViewObject MyNewView(WindowPtr theWindow)
  86. {
  87.     TQ3Status                myStatus;
  88.     TQ3ViewObject            myView;
  89.     TQ3DrawContextObject        myDrawContext;
  90.     TQ3RendererObject        myRenderer;
  91.     TQ3CameraObject            myCamera;
  92.     TQ3GroupObject            myLights;
  93.     
  94.     myView = Q3View_New();
  95.     
  96.     //    Create and set draw context.
  97.     if ((myDrawContext = MyNewDrawContext(theWindow)) == nil )
  98.         goto bail;
  99.         
  100.     if ((myStatus = Q3View_SetDrawContext(myView, myDrawContext)) == kQ3Failure )
  101.         goto bail;
  102.  
  103.     Q3Object_Dispose( myDrawContext ) ;
  104.     
  105.     // Create and set renderer.
  106.     //
  107.     // hacky way to do this, but since I wanted these snippets to have 
  108.     // a minimal interface, this will suffice
  109.     //
  110.     // change the next line to “#if 1” to use the WF renderer
  111.     
  112. #if 0
  113.     // this would use the wireframe renderer
  114.     myRenderer = Q3Renderer_NewFromType(kQ3RendererTypeWireFrame);
  115.     if ((myStatus = Q3View_SetRenderer(myView, myRenderer)) == kQ3Failure ) {
  116.         goto bail;
  117.     }
  118. #else
  119.     // this would use the interactive software renderer
  120.  
  121.     if ((myRenderer = Q3Renderer_NewFromType(kQ3RendererTypeInteractive)) != nil ) {
  122.         if ((myStatus = Q3View_SetRenderer(myView, myRenderer)) == kQ3Failure ) {
  123.             goto bail;
  124.         }
  125.     }
  126.     else {
  127.         goto bail;
  128.     }
  129. #endif
  130.  
  131.     Q3Object_Dispose( myRenderer ) ;
  132.     
  133.     //    Create and set camera.
  134.     if ( (myCamera = MyNewCamera(theWindow)) == nil )
  135.         goto bail;
  136.         
  137.     if ((myStatus = Q3View_SetCamera(myView, myCamera)) == kQ3Failure )
  138.         goto bail;
  139.  
  140.     Q3Object_Dispose( myCamera ) ;
  141.     
  142.     //    Create and set lights.
  143.     if ((myLights = MyNewLights()) == nil )
  144.         goto bail;
  145.         
  146.     if ((myStatus = Q3View_SetLightGroup(myView, myLights)) == kQ3Failure )
  147.         goto bail;
  148.         
  149.     Q3Object_Dispose(myLights);
  150.  
  151.     //    Done!!!
  152.     return ( myView );
  153.     
  154. bail:
  155.     //    If any of the above failed, then don't return a view.
  156.     return ( nil );
  157. }
  158.  
  159. //----------------------------------------------------------------------------------
  160.  
  161. TQ3DrawContextObject MyNewDrawContext(WindowPtr theWindow)
  162. {
  163.     TQ3DrawContextData        myDrawContextData;
  164.     TQ3MacDrawContextData    myMacDrawContextData;
  165.     TQ3ColorARGB            ClearColor;
  166.     TQ3DrawContextObject    myDrawContext ;
  167.     
  168.     ClearColor.a = 1.0;
  169.     ClearColor.r = 1.0;
  170.     ClearColor.g = 1.0;
  171.     ClearColor.b = 1.0;
  172.     
  173.     //    Fill in draw context data.
  174.     myDrawContextData.clearImageMethod = kQ3ClearMethodWithColor;
  175.     myDrawContextData.clearImageColor = ClearColor;
  176.     
  177.     myDrawContextData.paneState = kQ3False;
  178.     myDrawContextData.maskState = kQ3False;
  179.     
  180.     myDrawContextData.doubleBufferState = kQ3True;
  181.  
  182.     myMacDrawContextData.drawContextData = myDrawContextData;
  183.     
  184.     myMacDrawContextData.window = (CGrafPtr) theWindow;        // this is the window associated with the view
  185.     myMacDrawContextData.library = kQ3Mac2DLibraryNone;
  186.     myMacDrawContextData.viewPort = nil;
  187.     myMacDrawContextData.grafPort = nil;
  188.     
  189.     //    Create draw context and return it, if it’s nil the caller must handle
  190.     myDrawContext = Q3MacDrawContext_New(&myMacDrawContextData) ;
  191.  
  192.     return myDrawContext ;
  193. }
  194.  
  195. //----------------------------------------------------------------------------------
  196.  
  197. TQ3CameraObject MyNewCamera(WindowPtr theWindow)
  198. {
  199.     TQ3CameraObject                    myCamera;
  200.     TQ3CameraData                    myCameraData;
  201.     TQ3ViewAngleAspectCameraData        myViewAngleCameraData;
  202.     TQ3Point3D                        cameraFrom     = { 0.0, 0.0, 30.0 };
  203.     TQ3Point3D                        cameraTo     = { 0.0, 0.0, 0.0 };
  204.     TQ3Vector3D                        cameraUp     = { 0.0, 1.0, 0.0 };
  205.     
  206.     float                             fieldOfView = .52359333333;
  207.     float                             hither         = 0.001;
  208.     float                             yon         = 1000;
  209.     
  210.     //    Fill in camera data.
  211.     myCameraData.placement.cameraLocation = cameraFrom;
  212.     myCameraData.placement.pointOfInterest = cameraTo;
  213.     myCameraData.placement.upVector = cameraUp;
  214.     
  215.     myCameraData.range.hither = hither;
  216.     myCameraData.range.yon = yon;
  217.     
  218.     myCameraData.viewPort.origin.x = -1.0;
  219.     myCameraData.viewPort.origin.y = 1.0;
  220.     myCameraData.viewPort.width = 2.0;
  221.     myCameraData.viewPort.height = 2.0;
  222.     
  223.     myViewAngleCameraData.cameraData = myCameraData;
  224.     myViewAngleCameraData.fov = fieldOfView ;
  225.     
  226.     // set up the aspect ratio based on the window
  227.     myViewAngleCameraData.aspectRatioXToY =  
  228.             (float) (theWindow->portRect.right - theWindow->portRect.left) / 
  229.             (float) (theWindow->portRect.bottom - theWindow->portRect.top);
  230.  
  231.     myCamera = Q3ViewAngleAspectCamera_New(&myViewAngleCameraData);    
  232.     
  233.     //    Return the camera.
  234.     return ( myCamera );
  235. }
  236.  
  237.  
  238. //----------------------------------------------------------------------------------
  239.  
  240. TQ3GroupObject MyNewLights()
  241. {
  242.     TQ3GroupPosition            myGroupPosition;
  243.     TQ3GroupObject            myLightList;
  244.     TQ3LightData                myLightData;
  245.     TQ3PointLightData        myPointLightData;
  246.     TQ3DirectionalLightData    myDirectionalLightData;
  247.     TQ3LightObject            myAmbientLight, myPointLight, myFillLight;
  248.     TQ3Point3D                pointLocation = { -10.0, 0.0, 10.0 };
  249.     TQ3Vector3D                fillDirection = { 10.0, 0.0, 10.0 };
  250.     TQ3ColorRGB                WhiteLight = { 1.0, 1.0, 1.0 };
  251.     
  252.     //    Set up light data for ambient light.  This light data will be used for point and fill
  253.     //    light also.
  254.  
  255.     myLightData.isOn = kQ3True;
  256.     myLightData.color = WhiteLight;
  257.     
  258.     //    Create ambient light.
  259.     myLightData.brightness = .2;
  260.     myAmbientLight = Q3AmbientLight_New(&myLightData);
  261.     if ( myAmbientLight == nil )
  262.         goto bail;
  263.     
  264.     //    Create point light.
  265.     myLightData.brightness = 1.0;
  266.     myPointLightData.lightData = myLightData;
  267.     myPointLightData.castsShadows = kQ3False;
  268.     myPointLightData.attenuation = kQ3AttenuationTypeNone;
  269.     myPointLightData.location = pointLocation;
  270.     myPointLight = Q3PointLight_New(&myPointLightData);
  271.     if ( myPointLight == nil )
  272.         goto bail;
  273.  
  274.     //    Create fill light.
  275.     myLightData.brightness = .2;
  276.     myDirectionalLightData.lightData = myLightData;
  277.     myDirectionalLightData.castsShadows = kQ3False;
  278.     myDirectionalLightData.direction = fillDirection;
  279.     myFillLight = Q3DirectionalLight_New(&myDirectionalLightData);
  280.     if ( myFillLight == nil )
  281.         goto bail;
  282.  
  283.     //    Create light group and add each of the lights into the group.
  284.     myLightList = Q3LightGroup_New();
  285.     if ( myLightList == nil )
  286.         goto bail;
  287.     myGroupPosition = Q3Group_AddObject(myLightList, myAmbientLight);
  288.     if ( myGroupPosition == 0 )
  289.         goto bail;
  290.     myGroupPosition = Q3Group_AddObject(myLightList, myPointLight);
  291.     if ( myGroupPosition == 0 )
  292.         goto bail;
  293.     myGroupPosition = Q3Group_AddObject(myLightList, myFillLight);
  294.     if ( myGroupPosition == 0 )
  295.         goto bail;
  296.  
  297.     Q3Object_Dispose( myAmbientLight ) ;
  298.     Q3Object_Dispose( myPointLight ) ;
  299.     Q3Object_Dispose( myFillLight ) ;
  300.  
  301.     //    Done!
  302.     return ( myLightList );
  303.     
  304. bail:
  305.     //    If any of the above failed, then return nothing!
  306.     return ( nil );
  307. }
  308.  
  309.  
  310. //----------------------------------------------------------------------------------
  311.  
  312.  
  313. void GetGroupBBox(
  314.     DocumentHdl            theDocument,
  315.     TQ3BoundingBox         *viewBBox)
  316. {
  317.     TQ3Point3D                     from     = { 0.0, 0.0, 1.0 };
  318.     TQ3Point3D                     to         = { 0.0, 0.0, 0.0 };
  319.     TQ3Vector3D                 up         = { 0.0, 1.0, 0.0 };
  320.     
  321.     float                         fieldOfView = .52359333333;
  322.     float                         hither         =  0.5;
  323.     float                         yon         =  1.5;
  324.     TQ3GroupObject                mainGroup = (**theDocument).fModel ;
  325.  
  326.     TQ3Status                    status;
  327.     
  328. #ifdef BETA_1_BUILD
  329.     Q3View_StartBounds( (**theDocument).fView );
  330.  
  331.     status = Q3DisplayGroup_BoundingBox(mainGroup, 
  332.                                         viewBBox, 
  333.                                         kQ3ComputeBoundsApproximate,
  334.                                          viewObject);
  335.  
  336.     Q3View_EndBounds( (**theDocument).fView );
  337. #else
  338.     status = GetDocumentGroupBoundingBox( theDocument , viewBBox) ;
  339. #endif
  340.                                         
  341.     //
  342.     //  If we have a point model, then the "viewBBox" would end up
  343.     //  being a "singularity" at the location of the point.  As
  344.     //  this bounding "box" is used in setting up the camera spec,
  345.     //  we get bogus input into Escher.
  346.     
  347.     {
  348.          float        xSize, ySize, zSize;
  349.         
  350.         xSize = viewBBox->max.x - viewBBox->min.x;
  351.         ySize = viewBBox->max.y - viewBBox->min.y;
  352.         zSize = viewBBox->max.z - viewBBox->min.z;
  353.  
  354.         if (xSize <= kQ3RealZero &&
  355.             ySize <= kQ3RealZero &&
  356.             zSize <= kQ3RealZero) {
  357.             
  358.             viewBBox->max.x += 0.0001;
  359.             viewBBox->max.y += 0.0001;
  360.             viewBBox->max.z += 0.0001;
  361.             
  362.             viewBBox->min.x -= 0.0001;
  363.             viewBBox->min.y -= 0.0001;
  364.             viewBBox->min.z -= 0.0001;
  365.         }
  366.     }
  367. }
  368.  
  369.  
  370.  
  371.  
  372. //------------------------------------------------------------------------
  373.  
  374.  
  375. TQ3Point3D AdjustCamera(
  376.     DocumentHdl            theDocument,
  377.     short                winWidth,
  378.     short                winHeight)
  379. {
  380.     float                         fieldOfView;
  381.     float                         hither;
  382.     float                         yon;
  383.     TQ3CameraPlacement            placement;
  384.     TQ3CameraRange                range;
  385.     TQ3BoundingBox                 viewBBox;
  386.     long                         fromAxis;    
  387.     float                         maxDimension;
  388.      float                        xSize, ySize, zSize;
  389.     float                        weights[2] = { 0.5, 0.5 };
  390.     TQ3Point3D                    points[2];
  391.     TQ3Vector3D                     viewVector;
  392.     TQ3Vector3D                    normViewVector;
  393.     TQ3Vector3D                    eyeToFrontClip;
  394.     TQ3Vector3D                    eyeToBackClip;
  395.     float                        viewDistance;
  396.     TQ3Vector3D                    diagonalVector;
  397.     float                        ratio;
  398.     TQ3CameraObject                camera;
  399.     
  400.     TQ3ViewObject                theView = (**theDocument).fView ;
  401.     TQ3GroupObject                mainGroup = (**theDocument).fModel ;
  402.     
  403.     TQ3Point3D                    *documentGroupCenter = &(**theDocument).fGroupCenter ;
  404.     float                        *documentGroupScale  = &(**theDocument).fGroupScale ;
  405.  
  406.     Q3View_GetCamera( theView, &camera);
  407.     GetGroupBBox( theDocument, &viewBBox);
  408.  
  409.     /*
  410.      *  If we have a point model, then the "viewBBox" would end up
  411.      *  being a "singularity" at the location of the point.  As
  412.      *  this bounding "box" is used in setting up the camera spec,
  413.      *  we get bogus input into Escher.
  414.      */
  415.     xSize = viewBBox.max.x - viewBBox.min.x;
  416.     ySize = viewBBox.max.y - viewBBox.min.y;
  417.     zSize = viewBBox.max.z - viewBBox.min.z;
  418.  
  419.     if (xSize <= kQ3RealZero &&
  420.         ySize <= kQ3RealZero &&
  421.         zSize <= kQ3RealZero)  {
  422.         viewBBox.max.x += 0.0001;
  423.         viewBBox.max.y += 0.0001;
  424.         viewBBox.max.z += 0.0001;
  425.         
  426.         viewBBox.min.x -= 0.0001;
  427.         viewBBox.min.y -= 0.0001;
  428.         viewBBox.min.z -= 0.0001;
  429.     }
  430.  
  431.     points[0] = viewBBox.min;
  432.     points[1] = viewBBox.max;
  433.  
  434.     Q3Point3D_AffineComb(points, weights, 2, documentGroupCenter);
  435.  
  436.     /*
  437.      *  The "from" point is on a vector perpendicular to the plane
  438.      *  in which the bounding box has greatest dimension.  As "up" is
  439.      *  always in the positive y direction, look at x and z directions.
  440.      */
  441.     xSize = viewBBox.max.x - viewBBox.min.x;
  442.     zSize = viewBBox.max.z - viewBBox.min.z;
  443.     
  444.     if (xSize > zSize) {
  445.         fromAxis = kQ3AxisZ;
  446.     } else {
  447.         fromAxis = kQ3AxisX;
  448.     }
  449.  
  450.     /*
  451.      *  Compute the length of the diagonal of the bounding box.
  452.      *
  453.      *  The hither and yon planes are adjusted so that the
  454.       *  diagonal of the bounding box is 7/8 the size of the
  455.       *  minimum dimension of the view frustum. The diagonal is used instead
  456.       *  of the maximum size (in x, y, or z) so that when you rotate
  457.       *  the object, the corners don't get clipped out.
  458.       */
  459.     Q3Point3D_Subtract(
  460.         &viewBBox.max,
  461.         &viewBBox.min,
  462.         &diagonalVector);
  463.  
  464.     maxDimension    =    Q3Vector3D_Length(&diagonalVector);
  465.     maxDimension    *=    8.0 / 7.0;
  466.     
  467.     ratio = 1.0 / maxDimension;
  468.             
  469.     *documentGroupScale = ratio;
  470.     
  471.     Q3Camera_GetPlacement(camera, &placement);
  472.  
  473.     Q3Point3D_Subtract(
  474.         &placement.cameraLocation,
  475.         &placement.pointOfInterest,
  476.         &viewVector);
  477.         
  478.     viewDistance = Q3Vector3D_Length(&viewVector);
  479.     
  480.     Q3Vector3D_Normalize(&viewVector, &normViewVector);
  481.     
  482.     Q3Vector3D_Scale(&normViewVector, 
  483.                      viewDistance - ratio * maxDimension/2.0,
  484.                      &eyeToFrontClip);
  485.                     
  486.     Q3Vector3D_Scale(&normViewVector, 
  487.                     viewDistance + ratio * maxDimension/2.0,
  488.                     &eyeToBackClip);
  489.  
  490.     hither     = Q3Vector3D_Length(&eyeToFrontClip);
  491.     yon     = Q3Vector3D_Length(&eyeToBackClip);
  492.     
  493.     fieldOfView = 2 * atan((ratio * maxDimension/2.0)/hither);
  494.  
  495.     range.hither                 = hither;
  496.     range.yon                     = yon;
  497.  
  498.     Q3Camera_SetRange(camera, &range);
  499.  
  500.     Q3ViewAngleAspectCamera_SetFOV(
  501.         camera, fieldOfView);
  502.  
  503.     Q3ViewAngleAspectCamera_SetAspectRatio(
  504.         camera, (float) winWidth / (float) winHeight);
  505.  
  506.     Q3Object_Dispose(camera);
  507.     
  508.     return( *documentGroupCenter );
  509. }
  510.  
  511.  
  512.